#![allow(clippy::upper_case_acronyms)]
//! 参考 nemu 添加的模块，本来应该用上的，但是目前不知道有啥意思，就先放着。。。
//! 如果之后能感觉到有哪里写了重复的东西，就用这里重构一下，不然之后就删掉
//! 命名规则: S 表示源寄存器， D 表示目标寄存器， I 表示有符号立即数， U 表示无符号立即数
//! 所以 SSD 就是这条指令参数有 两个源寄存器和一个目标寄存器

use super::{Isa, RtlOf};

mod error;
mod exec_inner;

pub(crate) type Rtl64 = Rtl<i64, u64>;
pub(crate) type Rtl32 = Rtl<i32, u32>;

pub(crate) enum SSDOp {
    Add,
    Sub,
    Mul,
    Div,

    Slt, // set less than
    Sltu,

    Sl,
    Srl,
    Sra,

    Xor,
    Or,
    And,
}

pub(crate) enum SSIOp {
    Beq,
    Bne,

    Blt,
    Bge,
    Bltu,
    Bgeu,

    Store1,
    Store2,
    Store4,
    Store8,
}

pub(crate) enum SSUOp {}

pub(crate) enum SDIOp {
    Add,
    Slt, // set less than
    Xor,
    Or,
    And,

    Jal,

    Loadi1,
    Loadi2,
    Loadi4,
    Loadi8,
    Loadu1,
    Loadu2,
    Loadu4,

    Fence, // Fence Memory and I/O, 同步指令
}

pub(crate) enum SDUOp {
    Slt, // set less than
    Sl,
    Srl,
    Sra,
}

/// 无操作数
pub(crate) enum NoArgOp {
    FenceTso,
    Pause,
    ECall,
    EBreak,
    Trap, // 特殊指令，表示程序结束
}

pub(crate) enum DIOp {
    LoadI, // 加载立即数
    Aipc,  // Add Immediate to PC, rd = pc + sext(immediate[31:12] << 12)
    Jal,
}

pub(crate) enum Rtl<I, U> {
    SSD {
        rs1: usize,
        rs2: usize,
        rd: usize,
        op: SSDOp,
    },

    SDI {
        rs: usize,
        rd: usize,
        imm: I,
        op: SDIOp,
    },

    SSI {
        rs1: usize,
        rs2: usize,
        imm: I,
        op: SSIOp,
    },

    DI {
        rd: usize,
        imm: I,
        op: DIOp,
    },

    SSU {
        rs1: usize,
        rs2: usize,
        imm: U,
        op: SSUOp,
    },

    SDU {
        rs: usize,
        rd: usize,
        imm: U,
        op: SDUOp,
    },

    NoArg(NoArgOp),
}

pub(crate) fn exec<T: Isa>(cpu: &mut T::Cpu, mem: &mut T::Memory, rtl: RtlOf<T>) {
    match rtl {
        Rtl::SSD { rs1, rs2, rd, op } => exec_inner::exec_ssd::<T>(cpu, rs1, rs2, rd, op),
        Rtl::SDI { rs, rd, imm, op } => exec_inner::exec_sdi::<T>(cpu, mem, rs, rd, imm, op),
        Rtl::SSI { rs1, rs2, imm, op } => exec_inner::exec_ssi::<T>(cpu, mem, rs1, rs2, imm, op),
        Rtl::DI { rd, imm, op } => exec_inner::exec_di::<T>(cpu, rd, imm, op),
        Rtl::SSU { rs1, rs2, imm, op } => exec_inner::exec_ssu::<T>(cpu, rs1, rs2, imm, op),
        Rtl::SDU { rs, rd, imm, op } => exec_inner::exec_sdu::<T>(cpu, mem, rs, rd, imm, op),
        Rtl::NoArg(op) => exec_inner::exec_noarg::<T>(cpu, op),
    }
}
